using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace BinaryComparison
{
    public class FileSegmentation
    {
        private readonly int[] _borders;
        private readonly byte[] _pattern;
        public long CurrentIndex { get; private set; }
        public long LastIndex { get; private set; }
        public FileSegmentation(byte[] pattern, long currentIndex,long lastIndex)
        {
            _pattern = (byte[])pattern.Clone(); 
            _borders = new int[_pattern.Length + 1];
            CurrentIndex = currentIndex;
            LastIndex = lastIndex;
            preProcess(); 
        }

        private void preProcess()
        {
            var i = 0;
            var j = -1;
            _borders[i] = j;

            while (i < _pattern.Length)
            {
                while (j >= 0 && _pattern[i] != _pattern[j])
                {
                    j = _borders[j];
                }
                _borders[++i] = ++j;
            }
        }
        public long Search(Stream stream) //KMP搜索算法
        {
            long bytesRead = 0;

            int b;
            var j = 0;

            while ((b = stream.ReadByte()) != -1)
            {
                bytesRead++;

                while (j >= 0 && (byte)b != _pattern[j])
                {
                    j = _borders[j];
                }

                ++j;

                if (j == _pattern.Length)
                {
                    return bytesRead;
                }
            }

            return -1;
        }

        public void Start(Stream stream, Stream basestream, Stream basestream2)
        {
            long absolutestart = basestream.Position; // 用于记录匹配帧在流的起始位置
            long absoluteend = basestream.Position; // 用于记录匹配帧在流的末尾位置

            var ms = stream; //创建内存流

            while (ms.Position < ms.Length) //没有读到内存流末尾
            {
                var position = Search(ms); //搜索在内存流中匹配的位置

                if (position == -1) //找不到匹配位置，不再搜索
                {
                    basestream.Seek(basestream.Position - (_pattern.Length - 1), SeekOrigin.Begin);  //回退到前一帧不超过模式串长度位置                                       
                    break;
                }
                else //找到
                {
                    absoluteend = basestream.Position - (ms.Length - ms.Position + _pattern.Length) - 1; // 确定该帧在原文件流对应绝对位置
                    absolutestart = absoluteend + 1; // 更新下一个切片的起始位置
                                                    
                }

               // Console.WriteLine($"CurrentIndex: {CurrentIndex}, absoluteend: {absoluteend}");

                basestream2.Seek(CurrentIndex, SeekOrigin.Begin);

                LastIndex = absoluteend;

                byte[] frame = new byte[LastIndex - CurrentIndex + 1];
                
                CurrentIndex = absolutestart;
               
                int bytesRead = basestream2.Read(frame, 0, frame.Length);

                Console.WriteLine("帧数据：");
                foreach (byte b in frame)
                {
                    Console.Write("{0:X2} ", b);
                }
                Console.WriteLine();

            }

            if (basestream.Position + _pattern.Length > basestream.Length)
            {
                // 将最后一帧的数据输出
                byte[] remainingData = new byte[basestream2.Length - CurrentIndex];
                int bytesRead = basestream2.Read(remainingData, 0, remainingData.Length);

                Console.WriteLine("帧数据：");
                foreach (byte b in remainingData)
                {
                    Console.Write("{0:X2} ", b);
                }
                Console.WriteLine();

            }
        }


    }
}

